package com.sunye.elasticsearch.controller;

import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.sunye.elasticsearch.entity.*;
import com.sunye.elasticsearch.repository.EsDogIndexRepository;
import com.sunye.elasticsearch.service.EsDogIndexService;
import com.sunye.elasticsearch.service.EsDogService;
import jodd.util.StringUtil;
import lombok.extern.slf4j.Slf4j;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.aggregations.*;
import org.elasticsearch.search.aggregations.bucket.terms.Terms;
import org.elasticsearch.search.aggregations.bucket.terms.TermsAggregationBuilder;
import org.elasticsearch.search.aggregations.metrics.CardinalityAggregationBuilder;
import org.elasticsearch.search.aggregations.metrics.ParsedCardinality;
import org.elasticsearch.search.aggregations.metrics.ValueCountAggregationBuilder;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.elasticsearch.core.*;
import org.springframework.data.elasticsearch.core.query.NativeSearchQuery;
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.io.IOException;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;

@Slf4j
@RestController
@RequestMapping("/elasticsearchController")
public class ElasticsearchController {

    @Autowired
    private EsDogService esDogService;


    @Autowired
    private EsDogIndexService esDogIndexService;


    /**
     * ES
     */
    @Autowired
    private ElasticsearchOperations restTemplate;


    @Autowired
    private ElasticsearchRestTemplate elasticsearchRestTemplate;


    @Autowired
    private EsDogIndexRepository esDogIndexRepository;

    @Autowired
    private RestHighLevelClient restHighLevelClient;

    /**
     * 索引(index)
     * ⼀个索引可以理解成⼀个关系型数据库。
     * 类型(type)
     * ⼀种type就像⼀类表，⽐如user表，order表。
     * 注意：
     * ES 5.x中⼀个index可以有多种type。
     * ES 6.x中⼀个index只能有⼀种type。
     * ES 7.x以后已经移除type这个概念。
     * 映射(mapping)
     * mapping 相当于关系型数据库中的表结构。
     * ⽂档(document)
     * ⼀个document相当于关系型数据库中的⼀⾏记录。
     * 字段(field)
     * 相当于关系型数据库表的字段
     * 集群(cluster)
     * 集群由⼀个或多个节点组成，⼀个集群有⼀个默认名称"elasticsearch"。
     * 节点(node)
     * 集群的节点，⼀台机器或者⼀个进程
     * 分⽚和副本(shard)
     * 副本是分⽚的副本。分⽚有主分⽚(primary Shard)和副本分⽚(replica Shard)之分。
     * ⼀个Index数据在物理上被分布在多个主分⽚中，每个主分⽚只存放部分数据。
     * 每个主分⽚可以有多个副本，叫副本分⽚，是主分⽚的复制。
     */


    /**
     * 初始化索引
     */
    @RequestMapping("/init")
    public void init(){
        esDogIndexService.init();
    }


    @RequestMapping("/selectAll")
    public Iterable selectAll(){
        return esDogService.selectAll();
    }


    //id是卖点的id  此方法暂时不好用
    //http://localhost:8088/elasticsearchController/changeSellingpoint?id=9&advantageDescribe=很优秀
    @RequestMapping("/changeSellingpoint")
    public void changeSellingpoint(ChangeSelling changeSelling){
        esDogService.changeSellingpoint(changeSelling);
    }


    //http://localhost:8088/elasticsearchController/searchDogsByEs/1/10?keyword=春寒料峭&color=白&recommend=1&price=200_1000
    //http://localhost:8088/elasticsearchController/searchDogsByEs/1/10?categoryId=1
    //http://localhost:8088/elasticsearchController/searchDogsByEs/1/10?sellingPointIds=1,2  (嵌套查询and)
    //http://localhost:8088/elasticsearchController/searchDogsByEs/1/10?skuIds=1,2  (嵌套查询or)
    //http://localhost:8088/elasticsearchController/searchDogsByEs/1/10?position=40.258397_110.742781&sort=price_desc (经纬度排序)
    @GetMapping("/searchDogsByEs/{start}/{size}")
    public PageVO<EsDogIndex> searchDogsByEs(EsDogSearchDTO dogSearchDTO, @PathVariable Integer start, @PathVariable Integer size) {
//        boolean exists = restTemplate.indexOps(EsDogIndex.class).exists();
//        if (!exists) {
//            esDogIndexService.init();
//        }
        if (start == null || start.equals(0)) {
            start = 1;
        }
        if (size == null || size.equals(0)) {
            size = 10;
        }
        PageVO<EsDogIndex> pageVO = new PageVO<>(start,size);
        try {
            NativeSearchQueryBuilder searchQueryBuilder = esDogService.searchDogsByEs(dogSearchDTO, pageVO);
            NativeSearchQuery searchQuery = searchQueryBuilder.build();
            log.info("searchGoods DSL:{}", searchQuery.getQuery());
            SearchHits<EsDogIndex> searchHits = restTemplate.search(searchQuery, EsDogIndex.class);
            if (searchHits.getTotalHits() > 0) {
                List<EsDogIndex> searchProductList = searchHits.stream().map(SearchHit::getContent).collect(Collectors.toList());
                pageVO.setPageNum(start);
                pageVO.setPageSize(size);
                pageVO.setRows(searchProductList);
                pageVO.setTotal(searchHits.getTotalHits());
                pageVO.setPages((int) Math.ceil((double) pageVO.getTotal() / size));
            }
        }catch (Exception e){
            e.printStackTrace();
        }
        return pageVO;

    }

    //http://localhost:8088/elasticsearchController/searchDogsGroupBy?groupByAge=1&groupByAgeAndBreed=1&groupByMaxAge=1
    @GetMapping("/searchDogsGroupBy")
    public List searchDogsGroupBy(EsDogSearchDTO dogSearchDTO) {
        List list = esDogService.searchDogsGroupBy(dogSearchDTO);
        return list;
    }


}
